package cz.farin.mandelinka;


public class Maze {
	
	private int sizeX, sizeY;
	private int[] squares; 
	
	public static Maze createEmpty(int sizeX, int sizeY) {
		Maze maze = new Maze(sizeX, sizeY);
		maze.initEmptyMaze();
		return maze;
	}
	
	public static Maze createGrid(int sizeX, int sizeY) {
		Maze maze = new Maze(sizeX, sizeY);
		maze.initEmptyMaze();
		for(int x = 2; x < sizeX; x += 2) {
			for(int y = 2; y < sizeX; y += 2) {
				maze.set(x,y,SquareType.WALL);
			}
		}		
		return maze;
	}
	
	public SquareType get(Position pos) {	
		return get(pos.x, pos.y);
	}
	
	public SquareType get(int x, int y) {	
		if (x < 0 || x >= sizeX || y < 0 || y >= sizeY) {
			throw new IndexOutOfBoundsException();
		}
		int type = squares[cord2internalIndex(x, y)];
		return SquareType.values()[type];
	}
	
	protected void set(int x, int y, SquareType type) {
		squares[cord2internalIndex(x, y)] = type.ordinal();		
	}
	
	private Maze(int sizeX, int sizeY) {
		this.sizeX = sizeX;
		this.sizeY = sizeY;
		squares = new int[sizeX * sizeY];		
	}
	
	private void initEmptyMaze() {
		for(int y = 0; y < sizeY; y++) {
			for(int x = 0; x < sizeX; x++) { 				
				if (x == 0 || y == 0 || x == sizeX -1 || y == sizeY -1) {
					set(x,y,SquareType.WALL);
				} else {
					set(x,y,SquareType.PASSAGE);
				} 				
			}
		}
	}
	 
	
	private int cord2internalIndex(int x, int y) {
		return x + y * sizeX;
	}

	void fillSurroundings(int x, int y, Surroundings surroundings) {
		for(int xi = -1; xi <= 1; xi++) {
			for(int yi = -1; yi <= 1; yi++) {
				surroundings.get(xi, yi).setType(get(x + xi, y + yi));
			}
		}		
	}
	
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		for(int y = 0; y < sizeY; y++) {
			for(int x = 0; x < sizeX; x++) {
				SquareType sqType = get(x, y);
				switch (sqType) {
				case WALL:
					sb.append("x");
					break;
				case PASSAGE:
					sb.append(".");
					break;
				case MARK:
					sb.append("$");
					break;
				default:
					sb.append("?");
					break;
				}				 				
			}
			sb.append('\n');
		}
		return sb.toString();
	}

	public int getSizeX() {
		return sizeX;
	}

	public int getSizeY() {
		return sizeY;
	}
	

}
